package ap.project.controller.service;

import org.json.JSONException;
import org.json.JSONObject;

import android.content.Context;
import android.graphics.Point;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnTouchListener;
import ap.project.controller.main.Connection;
import ap.project.controller.main.Constants;

public class GameControls implements OnTouchListener {

	public Point touchingPoint = new Point(Constants.STARTX, Constants.STARTY);
	public Boolean shooting = false;
	public boolean outdated = true;
	private GameResources gameJoystick;

	public int powerup;
	
	/**
	 * 
	 * @param context - context to be build upon
	 * Initialize the game control and set the resources
	 */
	public GameControls(Context context) {
		gameJoystick = new GameResources(context.getResources());
	}

	/*
	 * (non-Javadoc)
	 * @see android.view.View.OnTouchListener#onTouch(android.view.View, android.view.MotionEvent)
	 * 
	 * handles touch events and delegates them to correct function.
	 */
	public boolean onTouch(View v, MotionEvent event) {
		this.outdated = true;
		int action = event.getActionMasked();
		int pointerID = event.getPointerId(event.getActionIndex());
		int pointerCount = event.getPointerCount();

		switch (action) {
		case MotionEvent.ACTION_DOWN:
			checkTouchAction(event.getX(), event.getY());
			break;
			
		case MotionEvent.ACTION_POINTER_DOWN:
			checkTouchAction(event.getX(pointerID), event.getY(pointerID));
			break;

		case MotionEvent.ACTION_UP:
			checkUpAction(event.getX(), event.getY(),
					pointerCount);
			break;

		case MotionEvent.ACTION_POINTER_UP:
			checkUpAction(event.getX(pointerID), event.getY(pointerID),
					pointerCount);
			break;

		case MotionEvent.ACTION_MOVE:
			for (int i = 0; i < pointerCount; ++i) {
				checkTouchAction(event.getX(i), event.getY(i));
			}
			break;
		}

		return true;
	}

	/**
	 * Check touch release position (Action UP)
	 * 
	 * @param x
	 * @param y
	 * @param count
	 *            - amount of pointers active
	 */
	private void checkUpAction(float x, float y, int count) {
		if (count < 2) {
			shooting = false;
			snapBack();
		}
		if (x <= Constants.STARTX + gameJoystick.get_joystickBg().getWidth()
				+ Constants.BOUNDRY) {
			snapBack();
		} else if (x > Constants.STARTX
				+ gameJoystick.get_joystickBg().getWidth() + Constants.BOUNDRY) {
			shooting = false;
		}
	}

	private void snapBack() {
		touchingPoint.x = Constants.STARTX;
		touchingPoint.y = Constants.STARTY;
	}

	/**
	 * Check which action to execute based on the touch position(s)
	 * 
	 * @param x
	 * @param y
	 */
	public void checkTouchAction(float x, float y) {
		if ((x > (Constants.STARTX - (Constants.BOUNDRY * 2) - Constants.BACKGROUNDRADIUS))
				&& (x < (Constants.STARTX
						+ gameJoystick.get_joystickBg().getWidth() - Constants.BOUNDRY))
				&& (y > Constants.STARTY - Constants.BOUNDRY
						- Constants.BACKGROUNDRADIUS)
				&& (y < (Constants.STARTY
						+ gameJoystick.get_joystickBg().getHeight() + Constants.BOUNDRY))) {
			handleMove(x, y);
		} else if ((x > (Constants.STARTBUTTONX - Constants.BOUNDRY))
				&& (x < (Constants.STARTBUTTONX
						+ gameJoystick.get_shootButton().getWidth() + Constants.BOUNDRY))
				&& (y > (Constants.STARTBUTTONY - Constants.BOUNDRY))
				&& (y < (Constants.STARTBUTTONY
						+ gameJoystick.get_shootButton().getHeight() + Constants.BOUNDRY))) {
			handleShoot();
		} else if ((x > (Constants.STARTPOWERUPX1 - Constants.BOUNDRY))
				&& (x < (Constants.STARTPOWERUPX1 + gameJoystick.getPowerUp1()
						.getWidth()))
				&& (y > (Constants.POWERUPY - Constants.BOUNDRY))
				&& (y < (Constants.POWERUPY
						+ gameJoystick.getPowerUp1().getHeight() + Constants.BOUNDRY))) {
			handlePowerUp(1);
		} else if ((x > (Constants.STARTPOWERUPX2 - Constants.BOUNDRY))
				&& (x < (Constants.STARTPOWERUPX2 + gameJoystick.getPowerUp2()
						.getWidth()))
				&& (y > (Constants.POWERUPY - Constants.BOUNDRY))
				&& (y < (Constants.POWERUPY
						+ gameJoystick.getPowerUp2().getHeight() + Constants.BOUNDRY))) {
			handlePowerUp(2);
		} else if ((x > (Constants.STARTPOWERUPX3 - Constants.BOUNDRY))
				&& (x < (Constants.STARTPOWERUPX3 + gameJoystick.getPowerUp3()
						.getWidth()))
				&& (y > (Constants.POWERUPY - Constants.BOUNDRY))
				&& (y < (Constants.POWERUPY
						+ gameJoystick.getPowerUp3().getHeight() + Constants.BOUNDRY))) {
			handlePowerUp(3);
		}
	}

	/**
	 * 
	 * @param powerup - the power which has been used
	 * Send the power up which has been used.
	 */
	public void handlePowerUp(int powerup) {
		JSONObject jOb = new JSONObject();
		try {
			jOb.put("Code", Constants.CODEPOWERUP);
			jOb.put("Powerup", powerup);
			Connection.getInstance().send(jOb);

		} catch (JSONException e) {
			e.printStackTrace();
		}
		Connection.getInstance().send(jOb);
		GameSurface.handlePowerUp(powerup, false);
	}

	/**
	 * handle Shooting
	 */
	public void handleShoot() {
		shooting = true;
	}

	/**
	 * 
	 * @param x - move towards x position
	 * @param y - move towards y position
	 */
	public void handleMove(float x, float y) {
		touchingPoint.x = (int) x;
		touchingPoint.y = (int) y;

		// bound to a box
		if (touchingPoint.x < (Constants.STARTX - Constants.JOYSTICKRADIUS)) {
			touchingPoint.x = Constants.STARTX - Constants.JOYSTICKRADIUS;
		}
		if (touchingPoint.x > (Constants.STARTX + Constants.JOYSTICKRADIUS)) {
			touchingPoint.x = Constants.STARTX + Constants.JOYSTICKRADIUS;
		}
		if (touchingPoint.y < (Constants.STARTY - Constants.JOYSTICKRADIUS)) {
			touchingPoint.y = Constants.STARTY - Constants.JOYSTICKRADIUS;
		}
		if (touchingPoint.y > (Constants.STARTY + Constants.JOYSTICKRADIUS)) {
			touchingPoint.y = Constants.STARTY + Constants.JOYSTICKRADIUS;
		}
	}
}
